1. 文件目的
本文件旨在提供一套標準作業程序,用以評估與分析在 Raspberry Pi 5 硬體平台上運行的 PostgreSQL 資料庫之效能。效能測試是資料庫管理與應用程式優化的核心環節。本指南將不依賴外部效能測試工具,而是聚焦於如何利用 SQL 指令,特別是 EXPLAIN ANALYZE,以及 PostgreSQL 內建的基準測試工具 pgbench,來獲取量化的效能指標。
本指南涵蓋的範圍包括:測試資料的準備、查詢計畫的分析、索引對效能影響的量化比較,以及讀寫負載的基礎測試。
2. 核心概念與工具
在開始測試前,必須理解以下核心概念:
查詢計畫 (Query Plan): 當您執行一個 SQL 查詢時,PostgreSQL 的查詢規劃器 (Query Planner) 會分析多種執行該查詢的方式,並選擇一個它認為成本(Cost)最低的方案。這個方案即為「查詢計畫」。
EXPLAIN ANALYZE: 這是 PostgreSQL 中最強大的單一效能分析工具。EXPLAIN: 顯示查詢規劃器預計會使用的查詢計畫,而不實際執行它。ANALYZE: 實際執行查詢,並記錄下每個步驟的真實耗時與資源使用情況。兩者結合
EXPLAIN ANALYZE,可以讓我們比對預期與實際的效能,找出瓶頸所在。
循序掃描 (Sequential Scan): 從頭到尾讀取整張資料表來尋找符合條件的資料列。對於大型資料表而言,這通常是效能低落的根源。
索引掃描 (Index Scan): 透過索引(類似書本的目錄)來快速定位資料所在位置,避免讀取整張表,大幅提升查詢速度。
3. 程序一:準備基準測試資料
在空無一物的資料表上進行測試是沒有意義的。我們必須先建立一個包含足夠多資料的測試環境,才能模擬真實世界的負載。
登入資料庫: 使用
psql登入您先前建立的資料庫(例如my_project_db)。# 以 postgres 管理員身份登入 sudo -u postgres psql -d my_project_db建立測試資料表: 我們將建立一個
products資料表,包含多種資料類型。CREATE TABLE products ( id SERIAL PRIMARY KEY, product_sku UUID DEFAULT gen_random_uuid(), name VARCHAR(255) NOT NULL, category VARCHAR(50), price NUMERIC(10, 2), stock_count INTEGER, added_at TIMESTAMPTZ DEFAULT now() );插入大量測試資料: 使用
generate_series()函數,我們可以快速地產生大量(此處為 100 萬筆)的隨機資料。INSERT INTO products (name, category, price, stock_count) SELECT 'Product ' || s.id, CASE (s.id % 5) WHEN 0 THEN 'Electronics' WHEN 1 THEN 'Books' WHEN 2 THEN 'Clothing' WHEN 3 THEN 'Home Goods' ELSE 'Toys' END, (random() * 500 + 10)::NUMERIC(10, 2), (random() * 1000)::INTEGER FROM generate_series(1, 1000000) AS s(id);注意: 在 Raspberry Pi 5 上,此操作可能需要數分鐘時間,具體取決於 microSD 卡的寫入速度。
4. 程序二:執行 SQL 查詢效能測試
4.1. 基準測試:循序掃描 (Sequential Scan)
首先,我們在沒有任何索引的情況下,查詢一個特定的產品。
EXPLAIN ANALYZE SELECT * FROM products WHERE name = 'Product 500000';
預期輸出分析: 您會看到查詢計畫的頂層節點顯示為 Seq Scan on products。請特別記下最下方的 Execution Time,這將是我們的效能基準。在百萬筆資料中,這個時間可能長達數百毫秒。
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
Seq Scan on products (cost=0.00..20526.00 rows=1 width=64) (actual time=0.024..158.361 rows=1 loops=1)
Filter: ((name)::text = 'Product 500000'::text)
Rows Removed by Filter: 999999
Planning Time: 0.106 ms
Execution Time: 158.391 ms <-- 記下此數值
4.2. 優化測試:索引掃描 (Index Scan)
現在,我們在 name 欄位上建立一個 B-Tree 索引。
CREATE INDEX idx_products_name ON products(name);
建立索引後,執行完全相同的查詢:
EXPLAIN ANALYZE SELECT * FROM products WHERE name = 'Product 500000';
預期輸出分析: 這次,查詢計畫應顯示為 Index Scan using idx_products_name on products。您會發現 Execution Time 大幅縮短,可能降至 1 毫秒以下。這清晰地展示了索引帶來的巨大效能提升。
QUERY PLAN
Index Scan using idx_products_name on products (cost=0.42..8.44 rows=1 width=60) (actual time=0.034..0.035 rows=1 loops=1)
Index Cond: ((name)::text = 'Product 500000'::text)
Planning Time: 0.338 ms
Execution Time: 0.053 ms <-- 與前一個數值進行比較
4.3. 聚合查詢測試
聚合查詢(如 GROUP BY)主要消耗 CPU 資源。此測試可評估伺服器在資料處理上的效能。
EXPLAIN ANALYZE SELECT category, AVG(price) FROM products GROUP BY category;
觀察其 Execution Time,並注意查詢計畫中可能出現的 HashAggregate 節點。
QUERY PLAN
Finalize GroupAggregate (cost=18985.15..18986.45 rows=5 width=40) (actual time=206.724..213.276 rows=5 loops=1)
Group Key: category
-> Gather Merge (cost=18985.15..18986.31 rows=10 width=40) (actual time=206.699..213.239 rows=15 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Sort (cost=17985.12..17985.13 rows=5 width=40) (actual time=202.269..202.271 rows=5 loops=3)
Sort Key: category
Sort Method: quicksort Memory: 25kB
Worker 0: Sort Method: quicksort Memory: 25kB
Worker 1: Sort Method: quicksort Memory: 25kB
-> Partial HashAggregate (cost=17985.00..17985.06 rows=5 width=40) (actual time=202.218..202.221 rows=5 loops=3)
Group Key: category
Batches: 1 Memory Usage: 24kB
Worker 0: Batches: 1 Memory Usage: 24kB
Worker 1: Batches: 1 Memory Usage: 24kB
-> Parallel Seq Scan on products (cost=0.00..15901.67 rows=416667 width=14) (actual time=0.014..45.071 rows=333333 loops=3)
Planning Time: 0.206 ms
Execution Time: 213.339 ms
5. 程序三:讀寫 (OLTP) 負載基準測試
單一的 SQL 查詢無法完全代表真實世界的應用負載。pgbench 是 PostgreSQL 內建的標準工具,用於模擬多個客戶端同時對資料庫進行讀寫操作(交易)。
注意: 以下指令需在 psql 之外的 Linux Shell 環境中執行。
初始化
pgbench環境: 此指令會建立pgbench所需的四張資料表。-s 10(scale factor 10)將建立一個中等大小的測試資料集(10 * 100,000 = 100 萬筆pgbench_accounts資料列)。pgbench -i -s 10 my_project_db執行基準測試: 此指令模擬 10 個客戶端 (
-c 10),使用 2 個執行緒 (-j 2),執行 1000 筆交易 (-t 1000)。pgbench -c 10 -j 2 -t 1000 my_project_db分析輸出結果: 測試結束後,您會看到一份報告。最重要的指標是
tps(transactions per second)。pgbench (17.5 (Ubuntu 17.5-0ubuntu0.25.04.1)) starting vacuum...end. transaction type: <builtin: TPC-B (sort of)> scaling factor: 10 query mode: simple number of clients: 10 number of threads: 2 maximum number of tries: 1 number of transactions per client: 1000 number of transactions actually processed: 10000/10000 number of failed transactions: 0 (0.000%) latency average = 5.689 ms initial connection time = 130.366 ms tps = 1757.718538 (without initial connection time)此處的
tps值(約 1757)可作為您 Raspberry Pi 5 在此特定負載下的 OLTP 效能基準。
6. 結論
本指南提供了一套基礎的 PostgreSQL 效能測試方法。透過 EXPLAIN ANALYZE,我們可以精確地診斷單一查詢的效能瓶頸,並驗證索引等優化手段的有效性。透過 pgbench,我們可以獲得一個關於伺服器處理並發讀寫交易能力的量化指標 (TPS)。
這些測試結果是後續進行系統調校(如修改 postgresql.conf 中的 shared_buffers、work_mem 等參數)或硬體升級(如使用更高速的 NVMe SSD 替代 microSD 卡)前後,評估效能變化的重要依據。